home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 359_11 / patch5.000 / GO32 / DEBUG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-11  |  18.7 KB  |  728 lines

  1. /* This is file DEBUG.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:175,26 */
  16. #include <stdio.h>
  17. #include <setjmp.h>
  18. #include <math.h>
  19. #include <dos.h>
  20.  
  21. #include "build.h"
  22. #include "types.h"
  23. #include "gdt.h"
  24. #include "tss.h"
  25. #include "utils.h"
  26. #include "unassmbl.h"
  27. #include "syms.h"
  28. #include "paging.h"
  29. #include "npx.h"
  30. #include "mono.h"
  31.  
  32. extern int was_exception, have_80387;
  33. jmp_buf back_to_debugger;
  34. int can_longjmp=0;
  35.  
  36. #if DEBUGGER
  37.  
  38. extern word32 dr[8];
  39. extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
  40.  
  41. typedef struct {
  42.     char *cp;
  43.     int t;
  44.     } item;
  45.  
  46. my_getline(char *buf, char *lasttoken)
  47. {
  48.   int idx, i, ch;
  49.   if (use_ansi)
  50.     printf("\033[0;32m");
  51.   mono_attr = MONO_NORMAL;
  52.   printf(">> %s", lasttoken);
  53.   for (i=0; lasttoken[i]; i++)
  54.     mputchar(8);
  55.   while (!bioskey(1));
  56.   for (i=0; lasttoken[i]; i++)
  57.     mputchar(' ');
  58.   for (i=0; lasttoken[i]; i++)
  59.     mputchar(8);
  60.   idx = 0;
  61.   if (use_ansi)
  62.     printf("\033[1;33m");
  63.   mono_attr = MONO_BOLD;
  64.   while (1)
  65.   {
  66.     ch = bioskey(0) & 0xff;
  67.     switch (ch)
  68.     {
  69.       case 10:
  70.       case 13:
  71.         buf[idx] = 0;
  72.         if (!idx && lasttoken[0])
  73.           printf("\r  \r");
  74.         else
  75.           mputchar('\n');
  76.         if (use_ansi)
  77.           printf("\033[0m");
  78.         mono_attr = MONO_NORMAL;
  79.         return;
  80.       case 27:
  81.         while (idx)
  82.         {
  83.           printf("\b \b");
  84.           idx--;
  85.         }
  86.         break;
  87.       case 8:
  88.         if (idx)
  89.         {
  90.           printf("\b \b");
  91.           idx--;
  92.         }
  93.         break;
  94.       default:
  95.         mputchar(ch);
  96.         buf[idx++] = ch;
  97.         break;
  98.     }
  99.   }
  100. }
  101.  
  102. typedef enum { Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
  103. DUMP, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
  104. CLS };
  105.  
  106. extern struct {
  107.   char *name;
  108.   int size;
  109.   int ofs;
  110.   } regs[];
  111.  
  112. item cmds[] = {
  113.     "g", CONT,
  114.     "go", CONT,
  115.     "cont", CONT,
  116.     "c", CONT,
  117.     "step", STEP,
  118.     "s", STEP,
  119.     "next", NEXT,
  120.     "n", NEXT,
  121.     "regs", REGS,
  122.     "r", REGS,
  123.     "set", SET,
  124.     "help", HELP,
  125.     "h", HELP,
  126.     "?", HELP,
  127.     "list", LIST,
  128.     "l", LIST,
  129.     "u", LIST,
  130.     "dump", DUMP,
  131.     "d", DUMP,
  132.     "da", DUMP_A,
  133.     "db", DUMP_B,
  134.     "dw", DUMP_W,
  135.     "dd", DUMP,
  136.     "quit", QUIT,
  137.     "q", QUIT,
  138.     "break", BREAK,
  139.     "b", BREAK,
  140.     "status", STATUS,
  141.     "where", WHERE,
  142.     "whereis", WHEREIS,
  143.     "npx", XNPX,
  144.     "cls", CLS,
  145.     0, 0
  146.     };
  147.  
  148. extern int debug_mode;
  149.  
  150. debugger()
  151. {
  152.   char buf[140], token[10];
  153.   char buf2[140], *name, lasttoken[140];
  154.   int i, n, s, len, rem_cmd, cmd, vstep, found;
  155.   word32 vaddr, v, rem_v, olddr7;
  156.   int32 delta;
  157.  
  158.   dr0 = dr1 = dr2 = ARENA;
  159.   dr3 = syms_name2val("_main") + ARENA;
  160.   if (undefined_symbol)
  161.     dr3 = tss_ptr->tss_eip + ARENA;
  162.   rem_cmd = Zero;
  163.   lasttoken[0] = 0;
  164.   setjmp(back_to_debugger);
  165.   can_longjmp = 1;
  166.   while (1)
  167.   {
  168.     if (debug_mode)
  169.     {
  170.       int found;
  171.       my_getline(buf, lasttoken);
  172.       token[0] = 0;
  173.       if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
  174.         buf[0] = 0;
  175.       if (token[0])
  176.         strcpy(lasttoken, token);
  177.       cmd = rem_cmd;
  178.       found = 0;
  179.       for (i=0; cmds[i].cp; i++)
  180.         if (strcmp(cmds[i].cp, token) == 0)
  181.         {
  182.           cmd = cmds[i].t;
  183.           found = 1;
  184.         }
  185.       if (!found && token[0])
  186.         cmd = Unknown;
  187.       if (rem_cmd != cmd)
  188.         vaddr = tss_ptr->tss_eip;
  189.     }
  190.     else
  191.     {
  192.       cmd = CONT;
  193.       debug_mode = 1;
  194.     }
  195.     switch (cmd)
  196.     {
  197.       case HELP:
  198.         printf("Commands:\n");
  199.         printf("go <v>\tg\tgo, stop at <v>\n");
  200.         printf("cont\tc\tcontinue execution\n");
  201.         printf("step\ts\tstep through current instruction\n");
  202.         printf("next\tn\tstep to next instruction\n");
  203.         printf("list\tl u\tlist instructions (takes addr, count)\n");
  204.         printf("dump\td\tdump memory (takes addr, count)\n");
  205.         printf("break\tb\tset breakpoint (takes which, addr)\n");
  206.         printf("status\t\tbreakpoint status\n");
  207.         printf("regs\tr\tprint registers\n");
  208.         printf("set\t\tset register/memory\n");
  209.         printf("npx\t\tdisplay 80387 contents\n");
  210.         printf("where\t\tdisplay list of active functions\n");
  211.         printf("whereis\t\tfind a symbol/location (takes wildcard or value)\n");
  212.         printf("cls\t\tclear screen\n");
  213.         printf("help\th,?\tprint help\n");
  214.         printf("quit\tq\tquit\n");
  215.         break;
  216.       case CONT:
  217.         sscanf(buf, "%s", buf);
  218.         if (buf[0])
  219.         {
  220.           v = syms_name2val(buf);
  221.           if (undefined_symbol)
  222.             break;
  223.           dr3 = v+ARENA;
  224.           dr7 |= 0xc0;
  225.         }
  226.         else
  227.           dr7 &= ~0xc0;
  228.         olddr7 = dr7;
  229.         dr7 = 0;
  230.         tss_ptr->tss_eflags |= 0x0100;
  231.         go_til_stop();
  232.         dr7 = olddr7;
  233.         if (tss_ptr->tss_irqn == 1)
  234.         {
  235.           tss_ptr->tss_eflags &= ~0x0100;
  236.           tss_ptr->tss_eflags |= 0x10000;
  237.           go_til_stop();
  238.           if (tss_ptr->tss_irqn == 1)
  239.             tssprint(tss_ptr);
  240.         }
  241.         print_reason();
  242.         dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  243.         break;
  244.       case STEP:
  245.         if (rem_cmd != cmd)
  246.           n = 1;
  247.         sscanf(buf, "%d", &n);
  248.         tss_ptr->tss_eflags |= 0x0100;
  249.         for (i=0; i<n; i++)
  250.         {
  251.           olddr7 = dr7;
  252.           dr7 = 0;
  253.           go_til_stop();
  254.           dr7 = olddr7;
  255.           print_reason();
  256.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  257.           if (tss_ptr->tss_irqn != 1)
  258.             break;
  259.         }
  260.         tss_ptr->tss_eflags &= ~0x0100;
  261.         break;
  262.       case NEXT:
  263.         if (rem_cmd != cmd)
  264.           n = 1;
  265.         sscanf(buf, "%d", &n);
  266.         for (i=0; i<n; i++)
  267.         {
  268.           olddr7 = dr7;
  269.           dr7 &= ~0xc0;
  270.           dr7 |= 0xc0;
  271.           if (last_unassemble_unconditional ||
  272.               last_unassemble_jump)
  273.             tss_ptr->tss_eflags |= 0x0100; /* step */
  274.           else
  275.             tss_ptr->tss_eflags &= ~0x0100;
  276.           go_til_stop();
  277.           dr7 = olddr7;
  278.           print_reason();
  279.           dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
  280.           if (tss_ptr->tss_irqn != 1)
  281.             break;
  282.         }
  283.         tss_ptr->tss_eflags &= ~0x0100;
  284.         break;
  285.       case WHERE:
  286.         v = tss_ptr->tss_ebp;
  287.         vaddr = tss_ptr->tss_eip;
  288.         printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  289.         name = syms_val2line(vaddr, &i, 0);
  290.         if (name)
  291.           printf(", line %d in file %s", i, name);
  292.         else if (delta)
  293.           printf("%+ld", delta);
  294.         mputchar('\n');
  295.         do {
  296.           if (v == 0)
  297.             break;
  298.           rem_v = peek32(v+ARENA);
  299.           if (rem_v == 0)
  300.             break;
  301.           vaddr = peek32(v+ARENA+4);
  302.           printf("0x%08lx %s", vaddr, syms_val2name(vaddr, &delta));
  303.           name = syms_val2line(vaddr, &i, 0);
  304.           if (name)
  305.             printf(", line %d in file %s", i, name);
  306.           else if (delta)
  307.             printf("%+ld", delta);
  308.           mputchar('\n');
  309.           v = rem_v;
  310.         } while ((v>=tss_ptr->tss_esp) && (v<0x90000000L));
  311.         break;
  312.       case WHEREIS:
  313.         sscanf(buf, "%s", buf2);
  314.         if (strpbrk(buf2, "*?"))
  315.         {
  316.           syms_listwild(buf2);
  317.           break;
  318.         }
  319.         if (buf2[0])
  320.           vaddr = syms_name2val(buf2);
  321.         if (undefined_symbol)
  322.           break;
  323.         name = syms_val2name(vaddr, &delta);
  324.         printf("0x%08lx %s", vaddr, name);
  325.         if (delta)
  326.           printf("+%lx", delta);
  327.         name = syms_val2line(vaddr, &i, 0);
  328.         if (name)
  329.           printf(", line %d in file %s", i, name);
  330.         mputchar('\n');
  331.         break;
  332.       case LIST:
  333.         if (rem_cmd != cmd)
  334.           n = 10;
  335.         buf2[0] = 0;
  336.         sscanf(buf, "%s %d", buf2, &n);
  337.         if (buf2[0] && strcmp(buf2, "."))
  338.           vaddr = syms_name2val(buf2);
  339.         if (undefined_symbol)
  340.           break;
  341.         for (i=0; i<n; i++)
  342.         {
  343.           vaddr = unassemble(vaddr, 0);
  344.           i += last_unassemble_extra_lines;
  345. /*          if (last_unassemble_unconditional)
  346.             break; */
  347.         }
  348.         break;
  349.       case DUMP_A:
  350.         buf2[0] = 0;
  351.         sscanf(buf, "%s %d", buf2, &n);
  352.         if (buf2[0])
  353.           vaddr = syms_name2val(buf2);
  354.         if (undefined_symbol)
  355.           break;
  356.         while (1)
  357.         {
  358.           word8 ch;
  359.           if (!page_is_valid(vaddr+ARENA))
  360.           {
  361.             printf("<bad address>\n");
  362.             break;
  363.           }
  364.           ch = peek8(vaddr+ARENA);
  365.           if (ch == 0)
  366.           {
  367.             mputchar('\n');
  368.             break;
  369.           }
  370.           if (ch < ' ')
  371.             printf("^%c", ch+'@');
  372.           else if ((ch >= ' ') && (ch < 0x7f))
  373.             mputchar(ch);
  374.           else if (ch == 0x7f)
  375.             printf("^?");
  376.           else if ((ch >= 0x80) && (ch < 0xa0))
  377.             printf("M-^%c", ch-0x80+'@');
  378.           else if (ch >= 0xa0)
  379.             printf("M-%c", ch-0x80);
  380.           vaddr++;
  381.         }
  382.         break;
  383.       case DUMP:
  384.       case DUMP_B:
  385.       case DUMP_W:
  386.         if (rem_cmd != cmd)
  387.           n = 4;
  388.         buf2[0] = 0;
  389.         sscanf(buf, "%s %d", buf2, &n);
  390.         if (buf2[0])
  391.           vaddr = syms_name2val(buf2);
  392.         if (undefined_symbol)
  393.           break;
  394.         s = 0;
  395.         len = n + (~((vaddr&15)/4-1) & 3);
  396.         for (i=-(vaddr&15)/4; i<len; i++)
  397.         {
  398.           if ((s&3) == 0)
  399.             printf("0x%08lx:", vaddr+i*4);
  400.           if ((i>=0) && (i<n))
  401.             printf(" 0x%08lx", peek32(vaddr+i*4+ARENA));
  402.           else
  403.             printf("           ");
  404.           if ((s & 3) == 3)
  405.           {
  406.             int j, c;
  407.             printf("  ");
  408.             for (j=0; j<16; j++)
  409.               if ((j+i*4-12>=0) && (j+i*4-12 < n*4))
  410.               {
  411.                 c = peek8(vaddr+j+i*4-12+ARENA);
  412.                 if (c<' ')
  413.                   mputchar('.');
  414.                 else
  415.                   mputchar(c);
  416.               }
  417.               else
  418.                 mputchar(' ');
  419.             printf("\n");
  420.           }
  421.           s++;
  422.         }
  423.         if (s & 3)
  424.           printf("\n");
  425.         vaddr += n*4;
  426.         break;
  427.       case BREAK:
  428.         vaddr = n = 0;
  429.         buf2[0] = 0;
  430.         sscanf(buf, "%d %s", &n, buf2);
  431.         if (buf2[0])
  432.           vaddr = syms_name2val(buf2);
  433.         if (undefined_symbol)
  434.           break;
  435.         dr[n] = vaddr + ARENA;
  436.         if (vaddr == 0)
  437.           dr7 &= ~(2 << (n*2));
  438.         else
  439.           dr7 |= 2 << (n*2);
  440.       case STATUS:
  441.         s = 0;
  442.         for (n=0; n<4; n++)
  443.         {
  444.           s = 1;
  445.           name = syms_val2name(dr[n]-ARENA, &delta);
  446.           printf("  dr%d  %s", n, name);
  447.           if (delta)
  448.             printf("+%#lx", delta);
  449.           if (name[0] != '0')
  450.             printf(" (0x%lx)", dr[n] - ARENA);
  451.           if (!(dr7 & (3 << (n*2))))
  452.             printf(" (disabled)");
  453.           mputchar('\n');
  454.         }
  455.         if (s == 0)
  456.           printf("  No breakpoints set\n");
  457.         break;
  458.       case REGS:
  459.         tssprint(tss_ptr);
  460.         unassemble(tss_ptr->tss_eip, 0);
  461.         break;
  462.       case SET:
  463.         cmd = Zero;
  464.         lasttoken[0] = 0;
  465.         buf2[0] = 0;
  466.         len = sscanf(buf, "%s %s", buf2, buf);
  467.         if (buf2[0] == 0)
  468.         {
  469.           break;
  470.         }
  471.         if (len > 1)
  472.         {
  473.           v = syms_name2val(buf);
  474.           if (undefined_symbol)
  475.             break;
  476.         }
  477.         found = 0;
  478.         for (i=0; regs[i].name; i++)
  479.           if (strcmp(regs[i].name, buf2) == 0)
  480.           {
  481.             found = 1;
  482.             if (len > 1)
  483.             {
  484.               switch (regs[i].size)
  485.               {
  486.                 case 1:
  487.                   *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  488.                   break;
  489.                 case 2:
  490.                   *(word16 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  491.                   break;
  492.                 case 4:
  493.                   *(word32 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  494.                   break;
  495.               }
  496.             }
  497.             else
  498.             {
  499.               switch (regs[i].size)
  500.               {
  501.                 case 1:
  502.                   printf("%02x ", *(word8 *)((word8 *)tss_ptr + regs[i].ofs));
  503.                   my_getline(buf, "");
  504.                   if (buf[0])
  505.                   {
  506.                     v = syms_name2val(buf);
  507.                     if (undefined_symbol)
  508.                       break;
  509.                     *(word8 *)((word8 *)tss_ptr + regs[i].ofs) = v;
  510.                   }
  511.                   break;
  512.                 case 2:
  513.                   printf("%04x ", *(word16 *)((word16 *)tss_ptr + regs[i].ofs));
  514.                   my_getline(buf, "");
  515.                   if (buf[0])
  516.                   {
  517.                     v = syms_name2val(buf);
  518.                     if (undefined_symbol)
  519.                       break;
  520.                     *(word16 *)((word16 *)tss_ptr + regs[i].ofs) = v;
  521.                   }
  522.                   break;
  523.                 case 4:
  524.                   printf("%08lx ", *(word32 *)((word32 *)tss_ptr + regs[i].ofs));
  525.                   my_getline(buf, "");
  526.                   if (buf[0])
  527.                   {
  528.                     v = syms_name2val(buf);
  529.                     if (undefined_symbol)
  530.                       break;
  531.                     *(word32 *)((word32 *)tss_ptr + regs[i].ofs) = v;
  532.                   }
  533.                   break;
  534.               }
  535.             }
  536.             break;
  537.           }
  538.         if (found)
  539.           break;
  540.         vaddr = syms_name2val(buf2);
  541.         if (undefined_symbol)
  542.           break;
  543.         if (len < 2)
  544.         {
  545.           v = syms_name2val(buf);
  546.           if (undefined_symbol)
  547.             break;
  548.           poke32(vaddr, v);
  549.         }
  550.         while (1)
  551.         {
  552.           printf("0x%08lx 0x%08lx", vaddr, peek32(vaddr+ARENA));
  553.           my_getline(buf, "");
  554.           if (buf[0])
  555.           {
  556.             if (strcmp(buf, ".") == 0)
  557.               break;
  558.             poke32(vaddr+ARENA, syms_name2val(buf));
  559.           }
  560.           vaddr += 4;
  561.         }
  562.         break;
  563.       case XNPX:
  564.         if (!have_80387)
  565.         {
  566.           printf("No 80387 present\n");
  567.           break;
  568.         }
  569.         save_npx();
  570.         printf("Control: 0x%04lx  Status: 0x%04lx  Tag: 0x%04lx\n",
  571.                npx.control, npx.status, npx.tag);
  572.         for (i=0; i<8; i++)
  573.         {
  574.           double d;
  575.           int tag;
  576.           int tos = (npx.status >> 11) & 7;
  577.           printf("st(%d)  ", i);
  578.           if (npx.reg[i].sign)
  579.             mputchar('-');
  580.           else
  581.             mputchar('+');
  582.           printf(" %04x %04x %04x %04x e %04x    ",
  583.                  npx.reg[i].sig3,
  584.                  npx.reg[i].sig2,
  585.                  npx.reg[i].sig1,
  586.                  npx.reg[i].sig0,
  587.                  npx.reg[i].exponent);
  588.           tag = (npx.tag >> (((i+tos)%8)*2)) & 3;
  589.           switch (tag)
  590.           {
  591.             case 0:
  592.               printf("Valid");
  593.               if (((int)npx.reg[i].exponent-16382 < 1000) &&
  594.                   ((int)npx.reg[i].exponent-16382 > -1000))
  595.               {
  596.                 d = npx.reg[i].sig3/65536.0 + npx.reg[i].sig2/65536.0/65536.0
  597.                   + npx.reg[i].sig1/65536.0/65536.0/65536.0;
  598.                 d = ldexp(d,(int)npx.reg[i].exponent-16382);
  599.                 if (npx.reg[i].sign)
  600.                   d = -d;
  601.                 printf("  %.16lg", d);
  602.               }
  603.               else
  604.                 printf("  (too big to display)");
  605.               mputchar('\n');
  606.               break;
  607.             case 1:
  608.               printf("Zero\n");
  609.               break;
  610.             case 2:
  611.               printf("Special\n");
  612.               break;
  613.             case 3:
  614.               printf("Empty\n");
  615.               break;
  616.           }
  617.         }
  618.         break;
  619.       case CLS:
  620.         if (use_mono)
  621.           mputchar(12);
  622.         else
  623.         {
  624.           _AH=15;
  625.           geninterrupt(0x10);
  626.           _AH = 0;
  627.           geninterrupt(0x10);
  628.           mputchar('\n');
  629.         }
  630.         break;
  631.       case QUIT:
  632.         return;
  633.       case Zero:
  634.         break;
  635.       default:
  636.         printf("Unknown command\n");
  637.         lasttoken[0] = 0;
  638.         cmd = Zero;
  639.         break;
  640.     }
  641.     if (undefined_symbol)
  642.     {
  643.       lasttoken[0] = 0;
  644.       cmd = Zero;
  645.       undefined_symbol = 0;
  646.     }
  647.     rem_cmd = cmd;
  648.     debug_mode = 1;
  649.   }
  650. }
  651. #endif /* DEBUGGER */
  652.  
  653. go_til_stop()
  654. {
  655.   tss_ptr = &a_tss;
  656.   while (1)
  657.   {
  658.     go32();
  659.     if (!was_exception)
  660.       return;
  661.     if (exception_handler())
  662.       return;
  663.   }
  664. }
  665.  
  666. #if DEBUGGER
  667. print_reason()
  668. {
  669.   int n, i;
  670.   i = tss_ptr->tss_irqn;
  671.   if ((i == 0x21) && ((tss_ptr->tss_eax & 0xff00) == 0x4c00))
  672.   {
  673.     tss_ptr->tss_eip -= 2; /* point to int 21h */
  674.     return;
  675.   }
  676.   if (use_ansi)
  677.     printf("\033[1;34m");
  678.   mono_attr = MONO_BOLD;
  679.   if (i != 1)
  680.   {
  681.     tssprint(tss_ptr);
  682.     if (tss_ptr != &a_tss)
  683.     {
  684.       printf("internal error: tss_ptr NOT a_tss\n");
  685.     }
  686.     if (i == 0x79)
  687.       printf("Keyboard interrupt\n");
  688.     else if (i == 0x75)
  689.     {
  690.       save_npx();
  691.       printf("Numeric Exception (");
  692.       if ((npx.status & 0x0241) == 0x0241)
  693.         printf("stack overflow");
  694.       else if ((npx.status & 0x0241) == 0x0041)
  695.         printf("stack underflow");
  696.       else if (npx.status & 1)
  697.         printf("invalid operation");
  698.       else if (npx.status & 2)
  699.         printf("denormal operand");
  700.       else if (npx.status & 4)
  701.         printf("divide by zero");
  702.       else if (npx.status & 8)
  703.         printf("overflow");
  704.       else if (npx.status & 16)
  705.         printf("underflow");
  706.       else if (npx.status & 32)
  707.         printf("loss of precision");
  708.       printf(") at eip=0x%08lx\n", npx.eip);
  709.       unassemble(npx.eip, 0);
  710.     }
  711.     else
  712.     {
  713.       printf("exception %d (%#02x) occurred", i, i);
  714.       if ((i == 8) || ((i>=10) && (i<=14)))
  715.         printf(", error code=%#lx", tss_ptr->tss_error);
  716.       mputchar('\n');
  717.     }
  718.   }
  719.   for (n=0; n<3; n++)
  720.     if ((dr6 & (1<<n)) && (dr7 & (3<<(n*2))))
  721.       printf("breakpoint %d hit\n", n);
  722.   if (use_ansi)
  723.     printf("\033[0m");
  724.   mono_attr = MONO_NORMAL;
  725. }
  726.  
  727. #endif /* DEBUGGER */
  728.